import datetime

from django.core.paginator import Paginator
from django.http import JsonResponse
from django.shortcuts import render, redirect, HttpResponse, HttpResponseRedirect
from django.urls import reverse
from django.db.models import Q, Sum, Count

import xlwt
from openpyxl import Workbook
from io import BytesIO

# Create your views here.
from site01.forms import DeviceTypeForm, SubProcessForm, EmployeesForm, ProcessForm, DeviceForm
from site01.models import SubProcess, DeviceType, Device, Process, Employees, EmployeeHours, MachineHours

from site01.tools import get_current_week

# 首页
def index(request):
    if request.method == 'POST':
        # 柱状图数据
        # 分工序统计员工数量
        data_items = [] # 工序名称，用作柱状图的项目
        datas = []      # 工序员工数量，用途柱状图的项目值
        # total_list = list(Employees.objects.filter(status=1).values('process').annotate(数量 = Count('jobname'))) # 正向查询各工序员工数量
        total_list1 = list(Process.objects.annotate(count=Count('employee')).values('name','count'))  # 通过工序表反向分类查询各个工序的员工数量
        for x in total_list1:
            data_items.append(x['name'])    # 把工序名称存入列表
            datas.append(x['count'])    # 把工序的员工数量值存入列表

        # print(total_list1)
        # for x in total_list:    # 对列表数据进行格式化处理:工序名称
        #     temp1 = list(Process.objects.filter(id=x['process']).values_list('name'))   # 把id值转化成name
        #     data_items.append(temp1[0][0])  # 去掉多余的嵌套
        # print(data_items)
        # datas1 = []
        # for y in total_list:    # 把值转化为格式化的列表：工序员工数量
        #     datas1.append(y['数量'])
        # print(datas1)

        # 返回数据
        return JsonResponse({'bar_datas':datas,'bar_items':data_items})
    else:
        total_employees = Employees.objects.filter(status=1).count()    # 在职人员数量
        total_process = Process.objects.filter(status=1).count()        # 正在使用的工序数量

        today = datetime.date.today()   # 当天的日期
        pre_today = today - datetime.timedelta(days=1)  # 前一天
        yesterday_hours = EmployeeHours.objects.filter(e_workday=pre_today).aggregate(Sum('e_hours'))   # 前一天工时数量
        # print(yesterday_hours)
        this_month_start = datetime.date(today.year, today.month, 1)    # 本月开始的第1天
        month_hours = EmployeeHours.objects.filter(e_workday__range=(this_month_start, today)).aggregate(Sum('e_hours'))    # 至今天止本月所有工时
        # print(month_hours)

        context = {
            'total_employees':total_employees,
            'total_process':total_process,
            'yesterday_hours':yesterday_hours,
            'month_hours':month_hours,

        }
        return render(request, 'site01/index.html',context)


# 显示设备类型
def device_type(request):
    devicetype = DeviceType.objects.filter(status=1)

    context = {
        "all_devicetype": devicetype,
    }
    return render(request, 'site01/device_type.html', context)


# 添加设备类型页
def add_device_type(request):
    dt_form = DeviceTypeForm()

    if request.method == 'POST':
        dt_form = DeviceTypeForm(request.POST)
        if dt_form.is_valid():
            name_get = dt_form.cleaned_data['typename']
            devicetype = DeviceType.objects.create(typename=name_get)
            devicetype.save()
            return redirect('device_type')

    context = {
        'dt_form': dt_form,
    }
    return render(request, 'site01/add_devicetype.html', context)


# 删除设备类型（把状态设置为9）
def del_device_type(request):
    del_id = request.POST.get('id')
    d_obj = DeviceType.objects.filter(id=del_id)
    d_obj.update(status=9)
    return redirect('device_type')


# 显示设备列表页
def device(request):
    all_devices = Device.objects.filter(status=1)

    context = {
        "all_devices": all_devices
    }
    return render(request, 'site01/device.html', context)


# 添加设备页
def add_device(request):
    d_form = DeviceForm()

    if request.method == 'POST':
        d_form = DeviceForm(request.POST)
        if d_form.is_valid():
            name_get = d_form.cleaned_data['name']
            sn_get = d_form.cleaned_data['sn']
            device_type_get = d_form.cleaned_data['devicetype']
            process_get = d_form.cleaned_data['process']
            d_obj = Device.objects.create(name=name_get, sn=sn_get, devicetype=device_type_get, process=process_get,
                                          status=1)
            d_obj.save()
            return redirect('device')

    context = {
        "d_form": d_form,
    }
    return render(request, 'site01/add_device.html', context)


# 删除设备
def del_device(request):
    del_id = request.POST.get('id')
    del_obj = Device.objects.filter(id=del_id)
    del_obj.update(status=9)
    return HttpResponse('ok')


# 显示工序页（只显示状态为1的）
def process(request):
    all_processes = Process.objects.filter(status=1)
    context = {
        "all_processes": all_processes,
    }
    return render(request, 'site01/process.html', context)


# 删除工序（把状态更改为9）
def del_process(request):
    del_id = request.POST.get('id')
    p_obj = Process.objects.filter(id=del_id)
    p_obj.update(status=9)
    return redirect('process')


# 增加工序
def add_process(request):
    p_form = ProcessForm()

    if request.method == 'POST':
        p_form = ProcessForm(request.POST)
        if p_form.is_valid():
            name_get = p_form.cleaned_data['name']

            process = Process.objects.create(name=name_get)
            process.save()
            return redirect('process')

    context = {
        'p_form': p_form,
    }
    return render(request, 'site01/add_process.html', context)


# 工序详情页
def view_process_detail(request, process_id):
    error_value = 1  # 默认状态值为1
    all_subprocess = SubProcess.objects.filter(process_id=process_id)
    # print(all_subprocess)

    if all_subprocess.count() == 0:  # 如果查询结果为空，则把错误状态值以为0
        error_value = 0
        # print(f"数据库中无记录:{error_value}")

    # print(f"**{SubProcess.objects.filter(process_id=process_id).first()}**")
    one = SubProcess.objects.filter(process_id=process_id).first()
    if one:
        name_get = one.process.name  # 获取工序对应的名称而不是ID号
    else:
        name_get = ''
    # print(name_get)

    context = {
        "process_name": name_get,
        "process_id": process_id,
        "all_subprocess": all_subprocess,
        "error_value": error_value,
    }
    return render(request, 'site01/view_process_detail.html', context)


# 显示员工列表页（只显示在职）
def employee(request,pIndex=1):
    employees_list = Employees.objects.filter(status=1).order_by()
    # 分页功能
    # 1、执行分页处理
    pIndex = int(pIndex)  # 对传入的页码值做整形转换
    page = Paginator(employees_list, 10)  # 对查询到的数据（eh_list）做分页（每页10条）处理，参数10表示每页的条数
    maxpages = page.num_pages  # 获取分页数据的最大页数
    # 2、判断传入的页码值有没有越界
    if pIndex > maxpages:
        pIndex = maxpages
    if pIndex < 1:
        pIndex = 1
    # 3、获取分页数据
    result_e_list = page.page(pIndex)  # 获取当前页数据
    plist = page.page_range  # 获取所有的页码列表
    # 4、使分页显示时每页的序号不是从1开始
    if pIndex == 1:
        ten_pIndex = 0
    else:
        ten_pIndex = (pIndex - 1) * 10

    context = {
        "employees": result_e_list,
        'pIndex':pIndex,
        'maxpages':maxpages,
        'plist':plist,
        'ten_pIndex':ten_pIndex,
    }
    return render(request, 'site01/employee.html', context)


# 增加员工页
def add_employee(request):
    e_form = EmployeesForm()

    if request.method == 'POST':
        e_form = EmployeesForm(request.POST)
        if e_form.is_valid():
            jobnumber_get = e_form.cleaned_data['jobnumber']
            jobname_get = e_form.cleaned_data['jobname']
            properties_get = e_form.cleaned_data['properties']
            status_get = e_form.cleaned_data['status']
            process_get = e_form.cleaned_data['process']
            employee_obj = Employees.objects.create(jobnumber=jobnumber_get, jobname=jobname_get,
                                                    properties=properties_get, status=status_get, process=process_get)
            employee_obj.save()
            return HttpResponseRedirect(reverse('employee',args=['1']))

    context = {
        'e_form': e_form,
    }
    return render(request, 'site01/add_employee.html', context)


# 删除员工页（把状态更改为离职）
def del_employee(request):
    del_id = request.POST.get("id")
    e_obj = Employees.objects.filter(id=del_id)
    e_obj.update(status=9)
    return HttpResponse('ok')


# 修改员工信息
def update_employee(request, employee_id):
    if request.method == 'POST':
        e_obj = Employees.objects.filter(id=employee_id).first()
        e_form = EmployeesForm(request.POST, instance=e_obj)  # 把默认数据传进去
        if e_form.is_valid():
            e_form.save()
        else:
            print(e_form.errors.as_json())
        return redirect('employee')
    else:
        e_obj = Employees.objects.filter(id=employee_id).first()
        e_form = EmployeesForm(instance=e_obj)

        context = {
            'e_form': e_form,
            'employee_id': employee_id,
        }
        return render(request, 'site01/update_employee.html', context)


# 员工导出到EXCEL文件
def export_excel(request):
    meta = Employees._meta  # 用于定义文件名, 格式为: app名.模型类名
    field_names = [field.name for field in meta.fields]  # 模型所有字段名
    print(request.session)
    response = HttpResponse(content_type='application/msexcel')  # 定义响应内容类型
    response['Content-Disposition'] = f'attachment; filename={meta}.xlsx'  # 定义响应数据格式
    wb = Workbook()  # 新建Workbook
    ws = wb.active  # 使用当前活动的Sheet表
    ws.append(field_names)  # 将模型字段名作为标题写入第一行
    for obj in Employees.objects.all():  # 遍历选择的对象列表
        for field in field_names:
            data = [f'{getattr(obj, field)}' for field in field_names]  # 将模型属性值的文本格式组成列表
        row = ws.append(data)  # 写入模型属性值
    wb.save(response)  # 将数据存入响应内容
    return response


# 导出到excel——1
def export_excel1(request):
    # 设置HTTPResponse的类型
    response = HttpResponse(content_type='application/vnd.ms-excel')
    response['Content-Disposition'] = 'attachment;filename=employees.xls'
    # 创建一个文件对象
    wb = xlwt.Workbook(encoding='utf8')
    # 创建一个sheet对象
    sheet = wb.add_sheet('employees')

    # 设置文件头的样式，这个不是必须的可以根据自己的需求进行更改
    style_heading = xlwt.easyxf("""
                font:
                    name Arial,
                    colour_index white,
                    bold on,
                    height 0xA0;
                align:
                    wrap off,
                    vert center,
                    horiz center;
                pattern:
                    pattern solid,
                    fore-colour 0x19;
                borders:
                    left THIN,
                    right THIN,
                    top THIN,
                    bottom THIN;
                """)
    # 定稿文件标题
    sheet.write(0, 0, 'ID', style_heading)
    sheet.write(0, 1, '工号', style_heading)
    sheet.write(0, 2, '姓名', style_heading)
    sheet.write(0, 3, '工序', style_heading)
    sheet.write(0, 4, '性质', style_heading)
    sheet.write(0, 5, '状态', style_heading)

    # 写入数据
    data_row = 1
    for i in Employees.objects.all():
        print(i.process)
        sheet.write(data_row, 0, i.id)
        sheet.write(data_row, 1, i.jobnumber)
        sheet.write(data_row, 2, i.jobname)
        sheet.write(data_row, 3, str(i.process))
        sheet.write(data_row, 4, i.properties)
        sheet.write(data_row, 5, i.status)
        data_row += 1

    # 写出到IO
    output = BytesIO()
    wb.save(output)
    # 重新定位到开始
    output.seek(0)
    response.write(output.getvalue())
    return response


# 人员工时
def employee_hours(request, pIndex=1):
    # eh_list = EmployeeHours.objects.all().order_by("e_workday")   # 获取所有数据
    today = datetime.date.today()   # 当天的日期
    this_month_start = datetime.date(today.year, today.month, 1)    # 把日期设置成本月第1天
    # 查询本月所有记录，并按日期进行升序排列
    eh_list = EmployeeHours.objects.filter(e_workday__range=(this_month_start, today)).order_by("-e_workday")
    # 搜索功能
    kw = request.GET.get("keyword",None)    # 获取前端搜索关键字
    mywhere = []    # 保存搜索关键字
    if kw:
        eh_list = EmployeeHours.objects.filter(Q(e_name__contains=kw)|Q(e_process__contains=kw)).order_by("-e_workday")
        mywhere.append('keyword=' +kw)

    # 分页功能
    # 1、执行分页处理
    pIndex = int(pIndex)    # 对传入的页码值做整形转换
    page = Paginator(eh_list,10)    # 对查询到的数据（eh_list）做分页（每页10条）处理，参数10表示每页的条数
    maxpages = page.num_pages   # 获取分页数据的最大页数
    # 2、判断传入的页码值有没有越界
    if pIndex > maxpages:
        pIndex = maxpages
    if pIndex < 1:
        pIndex = 1
    # 3、获取分页数据
    result_eh_list = page.page(pIndex)  # 获取当前页数据
    plist = page.page_range # 获取所有的页码列表

    '''    这个是以前使用 分类显示时的代码，现在不使用了 2021-12-29:取消了分类显示按钮
        # 默认情况页面只显示前一天数据
        if v_id == '0': # 昨天
            # 前一天
            pre_today = today - datetime.timedelta(days=1)  # 前一天
            employee_hours_list = EmployeeHours.objects.filter(e_workday=pre_today)
        elif v_id == '1':   # 今天
            employee_hours_list = EmployeeHours.objects.filter(e_workday=today)
        elif v_id == '3':   # 本周
            mon_day = get_current_week()
            employee_hours_list = EmployeeHours.objects.filter(e_workday__range=(mon_day,today)).order_by("e_workday")
        elif v_id == '6':   # 本月
            this_month_start = datetime.date(today.year,today.month,1)
            employee_hours_list = EmployeeHours.objects.filter(e_workday__range=(this_month_start,today)).order_by("e_workday")
        elif v_id == '8':   # 今年
            this_year_start = datetime.date(today.year,1,1)
            employee_hours_list = EmployeeHours.objects.filter(e_workday__range=(this_year_start,today)).order_by("e_workday")
        elif v_id == '9':   # 所有
            employee_hours_list = EmployeeHours.objects.all().order_by("e_workday")   # 获取所有数据
        else:
            employee_hours_list = EmployeeHours.objects.filter(e_workday=v_id)  # 按日期查询'''
    # 使分页显示时每页的序号不是从1开始
    if pIndex == 1:
        ten_pIndex = 0
    else:
        ten_pIndex = (pIndex - 1) * 10
    context = {
        "employee_hours_list": result_eh_list,  #分页后的当前页数据
        "plist":plist,  # 所有的页码列表
        "pIndex":pIndex,    # 当前页码
        "ten_pIndex":ten_pIndex,   # 使分页显示时从第二页开始的序号不是从1开始
        "maxpages":maxpages,    # 最大页码
        "mywhere":mywhere,  # 搜索关键字
    }
    return render(request, 'site01/e_hours.html', context)


# 添加人员工时记录
def add_employee_hour(request):
    if request.method == 'POST':
        '''     这是使用form的代码   
        ### 方法一
        eh_form = EmployeeHoursForm(request.POST)
        if eh_form.is_valid():
            pass
            # eh_form.save()
            ### 方法二
            # employee_get = eh_form.cleaned_data['employee']
            # process_get = eh_form.cleaned_data['process']
            # hours_get = eh_form.cleaned_data['hours']
            # eh_obj = EmployeeHours.objects.create(employee=employee_get,process=process_get,hours=hours_get)
            # eh_obj.save()
            
            '''
        name_get = request.POST.get("e-name")
        process_get = request.POST.get("e-process")
        hour_get = request.POST.get("work-hours")
        date_get = request.POST.get("work-day")
        print(f"**{name_get}**{process_get}**{hour_get}****")
        # print(datetime.date(date_get))

        eh_obj = EmployeeHours.objects.create(e_name=name_get, e_process=process_get, e_hours=float(hour_get),
                                              e_workday=date_get)
        eh_obj.save()
        # 使用HttpResponseRedirect返回经过reverse反向解析URL并添加了参数值的页面，使之能够准确返回对应的父页面
        return HttpResponseRedirect(reverse('employee_hours',args=['1']))
    elif request.method == 'GET':
        '''      这是使用form的代码  
        employee_list = Employees.objects.filter(status=1)  # 获取员工列表，做为下拉框
        process_list = Process.objects.all()

        eh_form = EmployeeHoursForm()
        '''
        all_e_name = Employees.objects.filter(status=1)  # 获取所有在职员工名单
        all_process = Process.objects.all()  # 获取所工序

    context = {
        'all_e_name': all_e_name,
        'all_process': all_process,
    }
    return render(request, 'site01/add_employee_hours.html', context)


# 批量添加人员工时---加载页面
def batch_edit_employee_hours(request,pName=None):
    # 获取传入的工序下所有人员
    temp = list(Employees.objects.filter(process__name=pName).values_list("jobname"))
    all_name_list = []
    for n in temp:
        for x in n:
            all_name_list.append(x)
    context = {
        'all_name_list':all_name_list,  # 人员名单
        'name_count':len(all_name_list),    # 人员数量
        'pName':pName,  # 工序
    }
    return render(request,'site01/batch_edit_employee_hours.html',context)


# Update 批量添加人员工时数据
def batch_update_employee_hours(request):
    ## 获取数据
    # print(request.POST)
    e_name_get = request.POST.get('e_name')
    e_name_get = e_name_get.split(',')  # 获取姓名列表
    if e_name_get[0] == '':
        e_name_get.remove('')   # 移除列表的空值
    e_hour_get = request.POST.get('ehours')
    workday_get = request.POST.get('workday')
    e_process_get = request.POST.get('e_process')
    # print(f"姓名：{e_name_get}")
    # print(f"工序：{e_process_get}")
    # print(f"工时：{e_hour_get}")
    # print(f"日期：{workday_get}")
    ## 把获取到的数据插入到数据库表中
    employees_hours_list = []   # 批量添加员工工时的对象列表
    for x in range(len(e_name_get)):    # 循环插入数据，并追加到对象列表
        # print(x,e_name_get[x])
        employees_hours_list.append(EmployeeHours(e_name=e_name_get[x],e_process=e_process_get,e_hours=e_hour_get,e_workday=workday_get))
    # print(employees_hours_list)
    EmployeeHours.objects.bulk_create(employees_hours_list) # 使用bulk_create方法一次将列表中数据插入到数据库表中

    return HttpResponseRedirect(reverse('employee_hours',args=[1]))


# 删除工时记录
def del_employee_hour(request,dID=0):
    '''删除暂时没有做提示框，以后再补上'''
    del_obj = EmployeeHours.objects.get(id=dID)
    del_obj.delete()
    return HttpResponseRedirect(reverse('employee_hours',args=[1]))


# 加载人员工时记录表单
def edit_employee_hour(request,uID=0):
    # 获取所有的工序
    process_list = Process.objects.values_list('name')
    temp1 = []
    for x in process_list:
        temp1.append(x[0])
    all_process = tuple(temp1)

    eh_obj = EmployeeHours.objects.get(id=uID)

    context = {
        "eh_obj":eh_obj,
        "all_process":all_process,
    }
    return render(request, 'site01/edit_employee_hour.html', context)


# 更新人员工时记录
def update_employee_hours(request,uID=0):
    if request.method == "POST":
        obj = EmployeeHours.objects.get(id=uID)
        obj.e_process = request.POST.get("e-process")
        obj.e_hours = request.POST.get("e-hours")
        obj.save()
        return HttpResponseRedirect(reverse('employee_hours',args=[1]))


# 获取人员的默认工序，使AJAX来设置相应的下拉框
def get_employee_process(request):
    if request.method == 'GET':
        e_name = request.GET.get('e_name')
        # print(f'******{e_name}*********')
        e_obj = Employees.objects.filter(jobname=e_name).first()
        e_process = e_obj.process
        # print(f'*******{e_process}*********')
    return HttpResponse(e_process)


def machine_hours(request):
    machine_hours_list = MachineHours.objects.all()

    context = {
        "machine_hours_list": machine_hours_list,
    }
    return render(request, 'site01/m_hours.html', context)


def update_subprocess(request, subprocess_id):
    s_obj = SubProcess.objects.get(id=subprocess_id)
    p_id = s_obj.process_id

    if request.method == "POST":
        # print(request.POST)
        s_obj = SubProcess.objects.filter(id=subprocess_id)
        new_name = request.POST.get("s_pName")
        s_obj.update(id=subprocess_id, name=new_name)
        # 使用HttpResponseRedirect返回经过reverse反向解析URL并添加了参数值的页面，使之能够准确返回对应的父页面
        return HttpResponseRedirect(reverse('view_process_detail', args=[str(p_id)]))
    else:
        s_form = SubProcessForm(instance=s_obj)

    context = {
        "s_obj": s_obj,
    }
    return render(request, 'site01/update_subprocess.html', context)


def del_subprocess(request):
    del_id = request.POST.get("id")  # 获取请求中的id值
    SubProcess.objects.filter(id=del_id).delete()  # 根据id值删除数据库表中对应记录

    return HttpResponse("删除成功")


def add_supprocess(request, process_id):
    if request.method == 'POST':
        s_name_get = request.POST.get("s_pName")
        s_obj = SubProcess.objects.create(name=s_name_get, process_id=process_id)
        s_obj.save()
        # 使用HttpResponseRedirect返回经过reverse反向解析URL并添加了参数值的页面，使之能够准确返回对应的父页面
        return HttpResponseRedirect(reverse('view_process_detail', args=[str(process_id)]))

    context = {
        'process_id': process_id,
    }
    return render(request, 'site01/add_subprocess.html', context)


# 测试光年框架
def main_page(request):
    return render(request, 'site01/main_page.html')
